home *** CD-ROM | disk | FTP | other *** search
/ Power Programmierung / Power-Programmierung (Tewi)(1994).iso / magazine / msysjour / vol07 / 02 / controls / init.c < prev    next >
C/C++ Source or Header  |  1992-02-29  |  10KB  |  365 lines

  1. /*
  2.  * INIT.C
  3.  *
  4.  * LibMain entry point and initialization code for the MicroScroll
  5.  * custom control DLL that is likely to be used once or very
  6.  * infrequently.
  7.  *
  8.  * Version 1.1, October 1991, Kraig Brockschmidt
  9.  */
  10.  
  11.  
  12. #include <windows.h>
  13. #include "muscrdll.h"
  14.  
  15.  
  16. HANDLE      hgInst;     //Need this for dialog editor style box.
  17.  
  18.  
  19. /*
  20.  * LibMain
  21.  *
  22.  * Purpose:
  23.  *  DLL-specific entry point called from LibEntry.  Initializes
  24.  *  the DLL's heap and registers the MicroScroll custom control
  25.  *  class.
  26.  *
  27.  * Parameters:
  28.  *  hInstance       HANDLE instance of the DLL.
  29.  *  wDataSeg        WORD segment selector of the DLL's data segment.
  30.  *  wHeapSize       WORD byte count of the heap.
  31.  *  lpCmdLine       LPSTR to command line used to start the module.
  32.  *
  33.  * Return Value:
  34.  *  HANDLE          Instance handle of the DLL.
  35.  *
  36.  */
  37.  
  38. HANDLE FAR PASCAL LibMain(HANDLE hInstance, WORD wDataSeg,
  39.                           WORD cbHeapSize, LPSTR lpCmdLine)
  40.     {
  41.     //Go register the control
  42.     if (FRegisterControl(hInstance))
  43.         {
  44.         hgInst=hInstance;
  45.  
  46.         if (0!=cbHeapSize)
  47.             UnlockData(0);
  48.  
  49.         return hInstance;
  50.         }
  51.  
  52.     hgInst=NULL;
  53.     return (HANDLE)NULL;
  54.     }
  55.  
  56.  
  57.  
  58.  
  59. /*
  60.  * FRegisterControl
  61.  *
  62.  * Purpose:
  63.  *  Registers the MicroScroll control class, including CS_GLOBALCLASS
  64.  *  to make the control available to all applications in the system.
  65.  *
  66.  * Parameters:
  67.  *  hInstance       HANDLE Instance of the application or DLL that will
  68.  *                  own this class.
  69.  *
  70.  * Return Value:
  71.  *  BOOL            TRUE if the class is registered, FALSE otherwise.
  72.  *                  TRUE is also returned if the class was already
  73.  *                  registered.
  74.  */
  75.  
  76. BOOL PASCAL FRegisterControl(HANDLE hInstance)
  77.     {
  78.     static BOOL     fRegistered=FALSE;
  79.     WNDCLASS        wc;
  80.     char            szClass[40];
  81.  
  82.     if (!fRegistered)
  83.         {
  84.         //Load the class name
  85.         if (0==LoadString(hInstance, IDS_CLASSNAME, szClass, 40))
  86.             return FALSE;
  87.  
  88.         wc.lpfnWndProc   = MicroScrollWndProc;
  89.         wc.cbClsExtra    = CBCLASSEXTRA;
  90.         wc.cbWndExtra    = CBWINDOWEXTRA;
  91.         wc.hInstance     = hInstance;
  92.         wc.hIcon         = NULL;
  93.         wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
  94.         wc.hbrBackground = COLOR_BTNFACE+1;
  95.         wc.lpszMenuName  = NULL;
  96.         wc.lpszClassName = szClass;
  97.         wc.style         = CS_DBLCLKS | CS_GLOBALCLASS |
  98.                            CS_VREDRAW | CS_HREDRAW;
  99.  
  100.         fRegistered=RegisterClass(&wc);
  101.         }
  102.  
  103.     return fRegistered;
  104.     }
  105.  
  106.  
  107.  
  108. /*
  109.  * LMicroScrollCreate
  110.  *
  111.  * Purpose:
  112.  *  Handles both WM_NCCREATE and WM_CREATE messages:
  113.  *    WM_NCCREATE:  Allocate control MUSCROLL structure.  Any sort
  114.  *                  of initialization that should force the create
  115.  *                  to fail should be included in this case.
  116.  *
  117.  *    WM_CREATE:    Fill the MUSCROLL structure; parse the text
  118.  *                  for initial min, max, and position for the
  119.  *                  MSS_TEXTHASRANGE style; clear all states;
  120.  *                  set the expansion handle to NULL.
  121.  *
  122.  * Parameters:
  123.  *  hWnd            HWND handle to the control window.
  124.  *  iMsg            WORD message, either WM_NCCREATE or WM_CREATE.
  125.  *  pMS             PMUSCROLL pointer to existing MUSCROLL structure.
  126.  *
  127.  * Return Value:
  128.  *  LONG            0L if memory could not be allocated on WM_NCCREATE.
  129.  *                  1L in all other cases.
  130.  */
  131.  
  132. LONG PASCAL LMicroScrollCreate(HWND hWnd, WORD iMsg, PMUSCROLL pMS,
  133.                                LPCREATESTRUCT lpCreate)
  134.     {
  135.     HANDLE          hMem;
  136.     BOOL            fTextRange;
  137.     WORD            iMin, iMax, iPos;
  138.  
  139.  
  140.     if (WM_NCCREATE==iMsg)
  141.         {
  142.         /*
  143.          * Allocate extra FIXED memory for the control's MUSCROLL
  144.          * structure and store that handle in the minimal window
  145.          * extra bytes allocated for the control.
  146.          *
  147.          * Note that LPTR includes LMEM_ZEROINIT, so all fields are
  148.          * initially zero.
  149.          */
  150.         hMem=LocalAlloc(LPTR, CBMUSCROLL);
  151.  
  152.         if (NULL==hMem)
  153.             return 0L;
  154.  
  155.         SetWindowWord(hWnd, GWW_MUSCROLLHMEM, (HANDLE)hMem);
  156.         }
  157.  
  158.     if (WM_CREATE==iMsg)
  159.         {
  160.         //Our associate is the parent by default.
  161.         pMS->hWndAssociate=(HWND)GetWindowWord(hWnd, GWW_HWNDPARENT);
  162.  
  163.  
  164.         //Copy styles
  165.         pMS->dwStyle  =lpCreate->style;
  166.  
  167.         /*
  168.          * Enforce exclusive MSS_VERTICAL and MSS_HORIZONTAL,
  169.          * defaulting to MSS_VERTICAL.
  170.          */
  171.         if ((MSS_VERTICAL & pMS->dwStyle) && (MSS_HORIZONTAL & pMS->dwStyle))
  172.             pMS->dwStyle &= ~MSS_HORIZONTAL;
  173.  
  174.         //Either parse the text or use defaults for initial range.
  175.         fTextRange=FALSE;
  176.  
  177.         if (MSS_TEXTHASRANGE & pMS->dwStyle)
  178.             {
  179.             fTextRange=FTextParse((LPSTR)lpCreate->lpszName,
  180.                                   &iMin, &iMax, &iPos);
  181.  
  182.             /*
  183.              * Verify that the position is in the given range.  If
  184.              * the position is outside the range, force it to the
  185.              * middle.
  186.              */
  187.             if (fTextRange)
  188.                 {
  189.                 if (iPos < iMin || iPos > iMax)
  190.                     iPos=(iMin + iMax) >> 1;
  191.                 }
  192.             }
  193.  
  194.  
  195.  
  196.         /*
  197.          * Use defaults if we never had MSS_TEXTHASRANGE or
  198.          * FTextParse failed.
  199.          */
  200.         pMS->iMin=(fTextRange ? iMin : IDEFAULTMIN);
  201.         pMS->iMax=(fTextRange ? iMax : IDEFAULTMAX);
  202.         pMS->iPos=(fTextRange ? iPos : IDEFAULTPOS);
  203.  
  204.         //Clear out all initial states.
  205.         StateClear(pMS, MUSTATE_ALL);
  206.  
  207.         //Indicate that all colors are defaults.
  208.         for (iMin=0; iMin < CCOLORS; iMin++)
  209.             pMS->rgCr[iMin]=(COLORREF)-1L;
  210.         }
  211.  
  212.     return 1L;
  213.     }
  214.  
  215.  
  216.  
  217. /*
  218.  * FTextParse
  219.  *
  220.  * Purpose:
  221.  *  Parses window text for a valid range and initial position.
  222.  *  This function is used when creating the control or setting the
  223.  *  window text to set the initial range and position but is also
  224.  *  used to validate text entered in the Style dialog in the Dialog
  225.  *  Editor interface if the MSM_TEXTHASRANGE style is selected.
  226.  *
  227.  *  The range and position must all be valid for any change to
  228.  *  occur in piMin, piMax, and piPos.
  229.  *
  230.  * Parameters:
  231.  *  psz             LPSTR pointer to the window text to parse out
  232.  *                  the range and the position.
  233.  *  piMin           LPINT pointer to location to store minimum.
  234.  *  piMax           LPINT pointer to location to store maximum.
  235.  *  piPos           LPINT pointer to location to store position.
  236.  *
  237.  * Return Value:
  238.  *  BOOL            TRUE if the function successfully initializes
  239.  *                  the range and position. FALSE if any part of
  240.  *                  the text is not a valid number between comma
  241.  *                  delimeters.
  242.  */
  243.  
  244. BOOL PASCAL FTextParse(LPSTR psz, LPINT piMin, LPINT piMax, LPINT piPos)
  245.     {
  246.     int          iMin;
  247.     int          iMax;
  248.     int          iCur;
  249.  
  250.     if (psz==NULL)
  251.         return FALSE;
  252.  
  253.     /*
  254.      * Parse off the bottom of the range.  Note that we depend
  255.      * on WTranslateUpToChar to modify psz to point to the character
  256.      * after the delimeter which is why we pass &psz.
  257.      */
  258.     iMin=WTranslateUpToChar(&psz, ',');
  259.  
  260.     //Check for valid value AND that there's text remaining.
  261.     if (-1==iMin || 0==*psz)
  262.         return FALSE;
  263.  
  264.     //Parse off the top of the range.
  265.     iMax=WTranslateUpToChar(&psz, ',');
  266.  
  267.     //Check for valid value AND that there's text remaining.
  268.     if (-1==iMax || 0==*psz)
  269.         return FALSE;
  270.  
  271.     //Parse off the position and validate it.
  272.     iCur=WTranslateUpToChar(&psz, ',');
  273.  
  274.     if (-1==iCur)
  275.         return FALSE;
  276.  
  277.     //Store the parsed values in the return locations.
  278.     *piMin=iMin;
  279.     *piMax=iMax;
  280.     *piPos=iCur;
  281.  
  282.     return TRUE;
  283.     }
  284.  
  285.  
  286.  
  287.  
  288.  
  289. /*
  290.  * WTranslateUpToChar
  291.  *
  292.  * Purpose:
  293.  *  Scans a string for digits, converting the series of digits to
  294.  *  an integer value as the digits are scanned.  Scanning stops
  295.  *  at chDelimeter or the end of the string.
  296.  *
  297.  *  If the scan sees a non-digit character, -1 is returned to indicate
  298.  *  error.  If the scan sees a null-terminator before any text, we
  299.  *  return 0.
  300.  *
  301.  * Parameters:
  302.  *  ppsz            LPSTR * pointer to pointer to the string to scan.
  303.  *                  On return, the pointer will point to the character
  304.  *                  after the delimeter OR the NULL terminator.
  305.  *
  306.  *                  We want a pointer to the pointer so we can modify
  307.  *                  that pointer for the calling function since we are
  308.  *                  using the return value for the parsed value
  309.  *
  310.  *  chDelimiter     char delimeter at which the scanning stops.
  311.  *
  312.  * Return Value:
  313.  *  WORD            -1 if the string contains non-digits excluding
  314.  *                  the comma.  Otherwise the converted value is
  315.  *                  returned and the pointer to the address after
  316.  *                  the comma is stored at ppsz.
  317.  */
  318.  
  319. WORD PASCAL WTranslateUpToChar(LPSTR FAR *ppsz, char chDelimeter)
  320.     {
  321.     WORD    wRet=0;
  322.     char    ch;
  323.     LPSTR   psz;
  324.  
  325.     psz=*ppsz;
  326.  
  327.     //Fail if there's no more string to parse.
  328.     if (0==*psz)
  329.         return -1;
  330.  
  331.     //Scan string, stopping at 0 or chDelimeter
  332.     while (ch=*psz)
  333.         {
  334.         if (ch==chDelimeter)
  335.             {
  336.             psz++;  //Skip delimeter
  337.             break;
  338.             }
  339.  
  340.         //Check for digits, returning -1 on a non-digit.
  341.         ch-='0';
  342.  
  343.         if (ch < 0 || ch > 9)
  344.             return -1;
  345.  
  346.         //Add up the value as we scan.
  347.         wRet=(wRet*10) + (WORD)ch;
  348.  
  349.         /*
  350.          * We increment psz here so if we hit a null-terminator
  351.          * psz is always valid.  If we incremented in the while
  352.          * statement then psz might be past the null-terminator
  353.          * and possibly invalid.
  354.          */
  355.         psz++;
  356.         }
  357.  
  358.     /*
  359.      * Store the new pointer and the value.  Note that the *psz++
  360.      * already incremented psz past the delimeter AND the zero.
  361.      */
  362.     *ppsz=psz;
  363.     return wRet;
  364.     }
  365.